﻿using System;
using System.IO;
using System.Diagnostics;
using Optum.SN.Infra.Core.TestBase.Properties;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Optum.SN.Infra.Core.TestBase
{
    /// <summary>
    /// Encapsulates common operations for integration testing web application.
    /// </summary>
    [TestClass]
    public abstract class WebTestBase : IDisposable
    {
        /// <summary>
        /// Starts IISExpress and hosts web application, when <see cref="IsLocalHost"/> is true.
        /// </summary>
        [TestInitialize]
        public void TestInitialize()
        {
            if (IsLocalHost)
                StartIis(); // Start IISExpress
        }
        /// <summary>
        /// Stops IISExpress.
        /// </summary>
        [TestCleanup]
        public void TestCleanup()
        {
            if (IisProcess != null && IisProcess.HasExited == false) // Ensure IISExpress is stopped
                IisProcess.Kill();
        }
        /// <summary>
        /// Disposes <see cref="IisProcess"/>, when not null and suppresses garbage collector.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
        }

        /// <summary>
        /// Gets settings value that identifies whether IIS Express should be run.
        /// </summary>
        protected virtual bool IsLocalHost { get { return Settings.Default.IsLocalHost; } }
        /// <summary>
        /// Gets base URI.
        /// </summary>
        protected abstract string BaseUri { get; }
        /// <summary>
        /// Gets the port, the web application is/should be hosted at.
        /// </summary>
        protected abstract int BaseUriPort { get; }
        /// <summary>
        /// Gets/sets folder path which has the configuration file for locally hosted web application.
        /// </summary>
        protected string WebServerFolder { private get; set; }
        /// <summary>
        /// Sets the <see cref="WebServerFolder"/> and <see cref="BaseUriPort"/> values.
        /// </summary>
        /// <param name="webServerFolder">Provides <see cref="WebServerFolder"/> value.</param>
        protected WebTestBase(string webServerFolder)
        {
            WebServerFolder = Path.GetFullPath(webServerFolder);
        }
        /// <summary>
        /// Frees managed and native resources.
        /// </summary>
        /// <param name="disposing">Disposes managed resource, <see cref="IisProcess"/>, when true.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (!disposing || IisProcess == null)
                return;
            IisProcess.Dispose();
            IisProcess = null;
        }
        /// <summary>
        /// Gets/sets external process.
        /// </summary>
        private Process IisProcess { get; set; }
        /// <summary>
        /// Starts external process, IISExpress and hosts web application.
        /// </summary>
        private void StartIis()
        {
            const string relativeIisExpressPath = @"\IIS Express\iisexpress.exe";

            var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);

            IisProcess = new Process
            {
                StartInfo =
                {
                    FileName = string.Format("{0}{1}", programFiles, relativeIisExpressPath),
                    Arguments = string.Format(@"/path:""{0}"" /port:{1}", WebServerFolder, BaseUriPort)
                }
            };
            IisProcess.Start();
        }
    }
}